home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-03-26 | 54.0 KB | 2,021 lines |
- (c) Copyright 1989 Commodore-Amiga, Inc. All rights reserved.
- The information contained herein is subject to change without notice, and
- is provided "as is" without warranty of any kind, either express or implied.
- The entire risk as to the use of this information is assumed by the user.
-
-
-
- Modular Event Processing
-
- by David N. Junod
-
- On the Amiga, input to an application can come from many different sources
- such as Intuition (through menu selections, gadget selections or the
- keyboard), Exec (through an inter-process communications method, such as
- ARexx) or even DOS (through a console-based command shell). With the
- increase in popularity of inter-process communication, it is more important
- than ever to use a modular programming methodology. A modular design
- incorporates reusable program components which are independent of the
- various user interfaces.
-
- The C source code that follows this article is an example of a modularly
- programmed application. It illustrates how to set up functions in a way
- that will keep the menu, gadget, and keyboard processing overhead to a
- minimum. This is achieved by setting up the program's functions with a
- consistent set of parameters, so that very different input sources can easily
- interface to the same functions. In this way the same code which handles a
- menu selection from Intuition can also be used to handle the command
- equivalent from an ARexx macro or a hot-key equivalent from the keyboard.
-
- The heart of this programming example is its function table. The function
- table is simply an array of pointers to all the modular functions within the
- program. Each component of the user interface is assigned a number that
- references an entry in the function table. Whenever a particular component
- of the user interface is triggered, the corresponding entry from the function
- table is executed. The example program, named modengine1.c, covers processing
- Intuition messages, ARexx macros, command shell input from a DOS console and
- hot-key equivalents.
-
- This engine can be used as the basic foundation for almost any application.
- The main processing loop would remain constant. You would add your own
- routines by including them in the function table and linking them in at
- compile time. Modengine1.c includes a Project Menu with all the standard
- items: New, Open, Save, Save As, About and Quit.
-
- The program also includes a small window showing four different Intuition
- gadget types: downpress, hold, release, and double-click. A fifth gadget
- will send an ARexx macro. There is also a menu named User which shows how
- you can provide a command shell using a DOS console window.
-
- The components of the program are shown in the figure below:
-
-
- Intuition Input ARexx Input Command Shell Input
- --------------- --------------- --------------------
- Handles menus, Handles ARexx Handles commands
- gadgets, and keyboard. scripts. from a DOS console.
- (mod_idcmp.c) (mod_arexx.c) (mod_dos.c)
-
-
-
- Input Event Processing
- ------------------------
- Converts events into
- function calls via lookup
- in a function table.
- (modengine1.c)
-
-
- Application Functions
- --------------------------
- A set of functions with
- consistent parameters that
- that perform the actions
- requested by the input event.
- (mod_funcs.c)
-
-
- Many of the functions such as those found in the Project and Edit menu strips,
- as well as the processing for the ESC, DEL and HELP keys, can remain the same
- from application to application. Using this approach will promote consistency
- between applications, and it cuts your coding time to a minimum by eliminating
- the need to re-code the common elements found in most applications.
-
- Another benefit of this approach is that it is easier to make your application
- user-configurable. You would only have to provide a means of editing the
- text and the function numbers of each of the menu items, gadgets and keys.
- Internationalization would become a very simple matter. As part of the
- implementation, modengine1.c illustrates some other techniques which are
- useful to Amiga programmers:
-
- o How to add an ARexx port to an application and handle the IPC events.
- o How to add a command shell to your application using a DOS console.
- o How to handle the project menu (and a project).
- o How to prevent overloading of mouse movements.
- o How to convert and handle raw keys.
- o How to determine if a gadget has been double-clicked.
- o How to avoid using global variables (using the UserData field of
- Intuition structures).
-
- The lmkfile (Lattice make file) is shown below. To compile modengine1.c,
- use the lmk command under Lattice 5.04. The listing is composed of six
- source files and two header files. These should be stored with the lmkfile
- in one directory.
-
- # lmk file for modengine1
- # Copyright (C) 1989, 1990 Commodore-Amiga, Inc.
- # written by David N. Junod
-
- COFILES = modengine1.o mod_misc.o mod_arexx.o mod_dos.o mod_idcmp.o mod_funcs.o
- CFLAGS = -cfist -ms -v -d2
-
- LFILES = $(COFILES)
- LDFLAGS = SMALLCODE SMALLDATA
- LLIBS = lib lib:lc.lib lib:amiga.lib lib:debug.lib
-
- .c.o:
- lc $(CFLAGS) $*
-
- all: modengine1
-
- modengine1: modengine1.ld
- BLink modengine1.ld to modengine1 NODEBUG
-
- modengine1.ld: $(COFILES) LMKfile
- blink <with <
- FROM lib:c.o lib:rexxglue.o $(LFILES)
- $(LDFLAGS)
- $(LLIBS)
- to modengine1.ld
- <
-
-
-
- /* mod.h
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- *
- * header file for modengine1
- * event processing engine structures & definitions
- *
- */
-
- #include <intuition/intuition.h>
- #include <rexx/storage.h> /* off of ARexx disk */
- #include <rexx/rxslib.h> /* off of ARexx disk */
- #include <exec/ports.h>
- #include <exec/memory.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <devices/inputevent.h>
- #include <proto/all.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
-
- /* mod_funcs.c: application functions */
- VOID NewFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID OpenFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID SaveFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID SaveAsFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID AboutFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID QuitFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID ChooseFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID DefineFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID UndoFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID HelpFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID ArrowFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID ShellFunc (struct AppInfo *, struct Message *, UBYTE *args );
- VOID WindowFunc (struct AppInfo *, struct Message *, UBYTE *args );
-
- #define APPNAME "Our Application"
-
- /* modengine1.c: initialization & dispatching routines */
- VOID main ( void );
- struct AppInfo *OpenAll ( void );
- VOID CloseAll (struct AppInfo *, int value , UBYTE *fmsg );
- BOOL HandlerFunc (struct AppInfo *, UBYTE * name, WORD function);
- struct MsgHandler * HandlerData (struct AppInfo *, UBYTE * name);
- BOOL AddMsgHandler (struct AppInfo *, struct MsgHandler *, BOOL);
- BOOL PerfFunc (struct AppInfo *, struct Message *, UBYTE *);
-
- /* mod_misc.c: misc. functions */
- BOOL NotifyUser (struct Window *, UBYTE *);
- BOOL CheckForChanges (struct AppInfo * ai);
-
-
-
-
- /*
- * message handler node
- */
- struct MsgHandler
- {
- struct Node mh_Node;
- ULONG mh_SigBits; /* signal bits to watch for */
- WORD mh_Status; /* current status */
-
- /* interface functions */
- BOOL (*mh_Func[4])(struct AppInfo *, struct MsgHandler *);
- VOID *mh_Data; /* handler context data */
- };
-
- #define MH_OPEN 0 /* make a handler active */
- #define MH_HANDLE 1 /* handle messages */
- #define MH_CLOSE 2 /* make a handler inactive */
- #define MH_SHUTDOWN 3 /* free resources and delete handler */
-
- /* component for our function table */
- struct Funcs
- {
- UBYTE *name;
- VOID (*func)(struct AppInfo *, struct Message *, UBYTE *);
- };
-
- #define NO_FUNCTION NULL /* no internal function defined for event */
-
- /*--- AREXX RELATED ITEMS -------------------------------------------------*/
- /* mod_arexx.c: AREXX message handling routines */
- struct MsgHandler *setup_arexx (struct AppInfo *, UBYTE *, UBYTE *, BOOL);
- BOOL open_arexx (struct AppInfo *, struct MsgHandler * );
- BOOL handle_arexx (struct AppInfo *, struct MsgHandler * );
- BOOL close_arexx (struct AppInfo *, struct MsgHandler * );
- BOOL shutdown_arexx (struct AppInfo *, struct MsgHandler * );
-
- #define AR_EXECUTE 0 /* ARexx status definitions */
- #define AR_SUSPEND 1
-
- /*--- DOS SHELL RELATED ITEMS ---------------------------------------------*/
- /* mod_dos.c: DOS message handling routines */
- struct MsgHandler *setup_dos (struct AppInfo *,UBYTE *,UBYTE *,UBYTE *, BOOL);
- BOOL open_dos (struct AppInfo *, struct MsgHandler *mh);
- BOOL handle_dos (struct AppInfo *, struct MsgHandler *mh);
- BOOL close_dos (struct AppInfo *, struct MsgHandler *mh);
- BOOL shutdown_dos (struct AppInfo *, struct MsgHandler *mh);
-
- /* DOS shell status definitions */
- #define AS_CLOSED 0
- #define AS_CLOSING 1
- #define AS_GOING 2
- #define AS_OPEN 3
-
- #define BUFFLEN 100
-
- /*--- IDCMP RELATED ITEMS -------------------------------------------------*/
- /* mod_idcmp.c: IDCMP message handling routines */
- struct MsgHandler * setup_idcmp ( struct AppInfo *,
- struct NewWindow *,struct KeyboardCMD *,struct Menu *,BOOL);
- BOOL open_idcmp (struct AppInfo *, struct MsgHandler *);
- BOOL handle_idcmp (struct AppInfo *, struct MsgHandler *);
- BOOL close_idcmp (struct AppInfo *, struct MsgHandler *);
- BOOL shutdown_idcmp (struct AppInfo *, struct MsgHandler *);
-
- /*--- MENU RELATED ITEMS ---*/
- struct EMenuItem /* Extended MenuItem structure */
- {
- struct MenuItem emi_Item; /* embedded MenuItem structure */
- UWORD emi_MenuID; /* ID used for function number to perform */
- VOID *emi_UserData; /* UserData (like other Intuition structs) */
- };
-
- /*--- GADGET RELATED ITEMS ---*/
- struct EGadget /* Extended Gadget structure */
- {
- struct Gadget eg_Gadget; /* embedded Gadget structure */
- WORD eg_Funcs[5]; /* Function array */
- };
- #define EG_DOWNPRESS 0 /* Extended Gadget function array pointers */
- #define EG_HOLD 1
- #define EG_RELEASE 2
- #define EG_DBLCLICK 3
- #define EG_ABORT 4
-
- /*--- KEYBOARD RELATED ITEMS ---*/
- #define MAXKEYS 512 /* some useful defines */
- #define SPECIAL 255
- #define ESC 27
- #define DELETE 127
- #define HELP (SPECIAL + '?')
- #define FUNC1 (SPECIAL + '0')
- #define FUNC2 (SPECIAL + '1')
- #define FUNC3 (SPECIAL + '2')
- #define FUNC4 (SPECIAL + '3')
- #define FUNC5 (SPECIAL + '4')
- #define FUNC6 (SPECIAL + '5')
- #define FUNC7 (SPECIAL + '6')
- #define FUNC8 (SPECIAL + '7')
- #define FUNC9 (SPECIAL + '8')
- #define FUNC10 (SPECIAL + '9')
- #define UP (SPECIAL + 'A')
- #define DOWN (SPECIAL + 'B')
- #define RIGHT (SPECIAL + 'C')
- #define LEFT (SPECIAL + 'D')
-
- /* component for our keyboard command array */
- struct KeyboardCMD
- {
- WORD key;
- WORD funcID;
- };
-
- /*--- GLOBAL DATA -----------------------------------------------------------*/
- /* AppInfo structure that contains our global variables */
- struct AppInfo
- {
- struct List MsgList; /* List of message handlers */
- ULONG sigbits; /* Sum of all signals */
- struct Funcs *FuncTable; /* Pointer to the function table */
- BOOL Done; /* Done with main loop? */
- WORD numcmds; /* Outstanding commands */
- LONG pri_ret; /* Primary error return value */
- LONG sec_ret; /* Secondary error return value */
- UBYTE *textrtn; /* Text return string */
-
- /* Project information */
- UBYTE ProjPath[255]; /* Path of project */
- UBYTE ProjName[31]; /* Name of project */
- BOOL Changed; /* Changes made to project? */
- };
-
-
-
- /* modengine1.h
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- *
- * header file for modengine1.c
- * application-specific arrays & definitions
- */
-
- /* Modular Function ID's */
- enum
- {
- NewID = 1,
- OpenID,
- SaveID,
- SaveAsID,
- AboutID,
- QuitID,
- ChooseID,
- DefineID,
- UndoID,
- HelpID,
- ArrowID,
- ShellID,
- Macro1ID,
- WindowID,
- LAST_ID
- };
-
- /* Modular Function Table */
- struct Funcs FTable[] =
- {
- {NULL, NO_FUNCTION}, /* padding, for alignment */
- {"NEW", NewFunc},
- {"OPEN", OpenFunc},
- {"SAVE", SaveFunc},
- {"SAVEAS", SaveAsFunc},
- {"ABOUT", AboutFunc},
- {"QUIT", QuitFunc},
- {"CHOOSE", ChooseFunc},
- {"DEFINE", DefineFunc},
- {"UNDO", UndoFunc},
- {"HELP", HelpFunc},
- {"ARROW", ArrowFunc},
- {"SHELL", ShellFunc},
- {"MACRO1", NO_FUNCTION}, /* calls an ARexx macro */
- {"WINDOW", WindowFunc},
- {NULL, NO_FUNCTION} /* end of array */
- };
-
- /* Text attribute to use for our text */
- struct TextAttr Topaz80 = {"topaz.font", 8, NULL, NULL};
-
- /* The menu structures for our 'application' */
- struct IntuiText UserT[] =
- {
- {2, 1, COMPLEMENT, 2, 1, &Topaz80, "Command Shell", NULL},
- {2, 1, COMPLEMENT, 2, 1, &Topaz80, "ARexx Macro 1", NULL}
- };
-
-
-
- /* MenuItem structure using our extended structure */
- struct EMenuItem UserI[] =
- {
- {NULL, 0, 0, 168, 9,
- ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP,
- 0, (APTR) & UserT[0], NULL, 'E', NULL, MENUNULL, ShellID, NULL},
-
- {&UserI[0].emi_Item, 0, 9, 168, 9,
- ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP,
- 0, (APTR) & UserT[1], NULL, '1', NULL, MENUNULL, Macro1ID, NULL}
- };
-
-
- /* Text for our Menu Items */
- struct IntuiText ProjT[] =
- {
- {2, 1, COMPLEMENT, 2, 1, &Topaz80, "New", NULL},
- {2, 1, COMPLEMENT, 2, 1, &Topaz80, "Open...", NULL},
- {2, 1, COMPLEMENT, 2, 1, &Topaz80, "Save", NULL},
- {2, 1, COMPLEMENT, 2, 1, &Topaz80, "Save As...", NULL},
- {2, 1, COMPLEMENT, 2, 1, &Topaz80, "About...", NULL},
- {2, 1, COMPLEMENT, 2, 1, &Topaz80, "Quit", NULL}
- };
-
- /* Extended Menu Item structures for our Application */
- struct EMenuItem ProjI[] =
- {
- {NULL, 0, 51, 148, 9,
- ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP,
- 0, (APTR) & ProjT[5], NULL, 'Q', NULL, MENUNULL, QuitID, NULL},
- {&ProjI[0].emi_Item, 0, 40, 148, 9,
- ITEMTEXT | ITEMENABLED | HIGHCOMP,
- 0, (APTR) & ProjT[4], NULL, NULL, NULL, MENUNULL, AboutID, NULL},
- {&ProjI[1].emi_Item, 0, 29, 148, 9,
- ITEMTEXT | ITEMENABLED | HIGHCOMP,
- 0, (APTR) & ProjT[3], NULL, NULL, NULL, MENUNULL, SaveAsID, NULL},
- {&ProjI[2].emi_Item, 0, 20, 148, 9,
- ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP,
- 0, (APTR) & ProjT[2], NULL, 'S', NULL, MENUNULL, SaveID, NULL},
- {&ProjI[3].emi_Item, 0, 9, 148, 9,
- ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHCOMP,
- 0, (APTR) & ProjT[1], NULL, 'O', NULL, MENUNULL, OpenID, NULL},
- {&ProjI[4].emi_Item, 0, 0, 148, 9,
- ITEMTEXT | ITEMENABLED | HIGHCOMP,
- 0, (APTR) & ProjT[0], NULL, NULL, NULL, MENUNULL, NewID, NULL}
- };
-
-
- /* Menu structure */
- struct Menu Menu2 =
- {NULL, 70, 0, 87, 0, MENUENABLED, "User", &UserI[1].emi_Item};
- struct Menu Menu1 =
- {&Menu2, 0, 0, 63, 0, MENUENABLED, "Project", &ProjI[5].emi_Item};
-
-
- /* Text for our Gadgets */
- struct IntuiText GadgT[] =
- {
- {2, 1, JAM2, 2, 1, &Topaz80, " DownPress ", NULL},
- {2, 1, JAM2, 2, 1, &Topaz80, " Hold ", NULL},
- {2, 1, JAM2, 2, 1, &Topaz80, " Release ", NULL},
- {2, 1, JAM2, 2, 1, &Topaz80, " Double-Click ", NULL},
- {2, 1, JAM2, 2, 1, &Topaz80, " ARexx Macro ", NULL}
- };
-
-
-
-
-
- /* extended Gadgets structures for our application */
- struct EGadget Gadg[] =
- {
- {NULL, 67, 15, 115, 10, NULL, GADGIMMEDIATE | RELVERIFY,
- BOOLGADGET, NULL, NULL, &GadgT[0], NULL, NULL, NULL, NULL,
- ChooseID, NO_FUNCTION, NO_FUNCTION, NO_FUNCTION, NO_FUNCTION},
-
- {&Gadg[0].eg_Gadget, 67, 29, 115, 10, NULL, GADGIMMEDIATE | RELVERIFY,
- BOOLGADGET, NULL, NULL, &GadgT[1], NULL, NULL, NULL, NULL,
- ArrowID, ArrowID, NO_FUNCTION, NO_FUNCTION, NO_FUNCTION},
-
- {&Gadg[1].eg_Gadget, 67, 43, 115, 10, NULL, GADGIMMEDIATE | RELVERIFY,
- BOOLGADGET, NULL, NULL, &GadgT[2], NULL, NULL, NULL, NULL,
- NO_FUNCTION, NO_FUNCTION, UndoID, NO_FUNCTION, NO_FUNCTION},
-
- {&Gadg[2].eg_Gadget, 67, 58, 115, 10, NULL, GADGIMMEDIATE | RELVERIFY,
- BOOLGADGET, NULL, NULL, &GadgT[3], NULL, NULL, NULL, NULL,
- ChooseID, NO_FUNCTION, NO_FUNCTION, DefineID, NO_FUNCTION},
-
- {&Gadg[3].eg_Gadget, 67, 73, 115, 10, NULL, GADGIMMEDIATE | RELVERIFY,
- BOOLGADGET, NULL, NULL, &GadgT[4], NULL, NULL, NULL, NULL,
- NO_FUNCTION, NO_FUNCTION, Macro1ID, NO_FUNCTION, NO_FUNCTION}
- };
-
- /*
- * Set up the keyboard function map. If you are a word processor,
- * then you could set up all the text-related keys to the same
- * function.
- */
- struct KeyboardCMD KeyArray[] =
- {
- {'u', UndoID}, /* u will call the Undo function */
- {ESC, QuitID}, /* ESC to quit */
- {HELP, HelpID}, /* HELP to call the help function */
- {UP, ArrowID}, /* Up arrow */
- {DOWN, ArrowID}, /* Down arrow */
- {FUNC1,Macro1ID}, /* Call an ARexx macro */
- {NULL, NO_FUNCTION} /* end of array */
- };
-
- /* NewWindow structure */
- struct NewWindow NewWindow =
- {
- 0, 10, 250, 90, 2, 1,
- NULL,
- WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | ACTIVATE | NOCAREREFRESH
- | REPORTMOUSE,
- &Gadg[4].eg_Gadget, NULL, APPNAME, NULL, NULL,
- 60, 30, 1024, 1024, WBENCHSCREEN,
- };
-
-
-
-
- /* ModEngine1.c
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- *
- * Modular event processing shell for Intuition
- */
- #include "mod.h"
- #include "ModEngine1.h"
-
- struct IntuitionBase *IntuitionBase = NULL; /* Required for Intuition processing */
-
- /* Main processing loop */
- VOID main ()
- {
- struct AppInfo *ai = NULL;
- struct List *list = NULL;
- struct Node *node = NULL;
- struct MsgHandler *mh = NULL;
- ULONG sig_rcvd;
-
- /* Obtain the needed resources */
- ai = OpenAll ();
- list = &(ai->MsgList);
-
- /* Process messages until user signals that they are done and no messages outstanding */
- while (!ai->Done || ai->numcmds)
- {
- /* wait for a message to come in */
- sig_rcvd = Wait (ai->sigbits);
-
- /* process signals */
- if (list->lh_TailPred != (struct Node *) list)
- for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
- {
- mh = (struct MsgHandler *) node;
- if (mh->mh_SigBits & sig_rcvd)
- (*mh->mh_Func[MH_HANDLE]) (ai, mh);
- }
- }
-
- /* Free up all the resources cleanly */
- CloseAll (ai, RETURN_OK, NULL);
- }
-
- /*--- Obtain the needed resources ---*/
- struct AppInfo *OpenAll ()
- {
- struct AppInfo *ai = NULL;
- /* open required libraries here */
- if (!(IntuitionBase = (struct IntuitionBase *)
- OpenLibrary ("intuition.library", 33L)))
- {
- CloseAll (ai, RETURN_FAIL, "Could not open intuition.library");
- }
-
- /* Allocate memory for all our variables */
- if (!(ai = (struct AppInfo *)
- AllocMem (sizeof (struct AppInfo), MEMF_CLEAR)))
- CloseAll (ai, RETURN_FAIL, "Not enough memory");
-
-
-
- /* Initialize the message handler list */
- NewList (&(ai->MsgList));
-
- /* set up the function table pointer */
- ai->FuncTable = &FTable[0];
-
- /* set up ARexx message handler */
- if (!(AddMsgHandler (ai,
- setup_arexx (ai, "OURAPP", "mod", TRUE),
- FALSE))) /* handler not required */
- CloseAll (ai, RETURN_FAIL, "Could not allocate ARexx resources");
-
- /* set up DOS command shell message handler */
- if (!(AddMsgHandler (ai,
- setup_dos (ai, "CON:0/150/600/50/Command Window",
- "Cmd>", "Waiting for message(s)\n", FALSE),
- FALSE))) /* handler not required */
- CloseAll (ai, RETURN_FAIL, "Could not allocate DOS resources");
-
- /* set up IDCMP message handler */
- if (!(AddMsgHandler (ai,
- setup_idcmp (ai, &NewWindow, KeyArray, &Menu1, TRUE),
- TRUE))) /* handler required */
- CloseAll (ai, RETURN_FAIL, "Could not allocate IDCMP resources");
-
- return (ai);
- }
-
-
- /*--- Free up all the resources that we obtained ---*/
- VOID CloseAll (struct AppInfo * ai, int value, UBYTE * fmsg)
- {
- struct List *list = &(ai->MsgList);
- struct Node *node = NULL, *nxtnode = NULL;
- struct MsgHandler *mh = NULL;
-
- /* display error message, if there is one */
- if (fmsg)
- NotifyUser (NULL, fmsg);
-
- /* shutdown all the handlers */
- if (list->lh_TailPred != (struct Node *) list)
- {
- node = list->lh_Head;
- while (nxtnode = node->ln_Succ)
- {
- mh = (struct MsgHandler *) node;
- (*mh->mh_Func[MH_SHUTDOWN]) (ai, mh);
- node = nxtnode;
- }
- }
-
- /* free our variable space */
- if (ai)
- FreeMem (ai, sizeof (struct AppInfo));
-
- /* close down libraries now */
- if (IntuitionBase)
- CloseLibrary ((struct Library *) IntuitionBase);
-
- exit (value);
- }
-
-
-
- /* add a message handler node to the handler list */
- BOOL AddMsgHandler (struct AppInfo * ai, struct MsgHandler * mh,
- BOOL needed)
- {
- BOOL retval = FALSE;
-
- if (mh)
- {
- AddTail (&(ai->MsgList), (struct Node *) mh);
- ai->sigbits |= mh->mh_SigBits;
- retval = TRUE;
- }
- return ( (BOOL)((needed) ? retval : TRUE) );
- }
-
-
- /* handle messages between function handlers */
- BOOL HandlerFunc (struct AppInfo * ai, UBYTE * name, WORD function)
- {
- BOOL retval = FALSE;
- struct MsgHandler * mh;
-
- if (mh = (struct MsgHandler *)FindName (&(ai->MsgList), name))
- {
- if (mh->mh_Func[function])
- retval = (*mh->mh_Func[function])(ai, mh);
- }
- return (retval);
- }
-
- /* get handler data */
- struct MsgHandler * HandlerData (struct AppInfo * ai, UBYTE * name)
- {
- return ( (struct MsgHandler *)FindName (&(ai->MsgList), name) );
- }
-
- /*
- * First checks to see if the command is an internal function and if so,
- * it executes the function. Otherwise, it passes the command to ARexx.
- */
- BOOL PerfFunc (struct AppInfo * ai, struct Message * msg, UBYTE * anchor)
- {
- extern BOOL send_rexx_command (UBYTE *, struct AppInfo *,
- struct MsgHandler *);
- struct MsgHandler * mh = NULL;
- register VOID (*func) (struct AppInfo *, struct Message *, UBYTE *);
- register UBYTE *args = anchor;
- register WORD cntr;
- BOOL retval = FALSE;
- UBYTE arg1[50];
-
- /* get the first word of the command string */
- args = stptok (args, arg1, sizeof (arg1), " ,");
-
- /* increment past first space */
- if (strlen (args) > 0)
- ++args;
-
- /* check the array to see if it is a name that we understand */
- for (cntr = 1, func = NO_FUNCTION;
- (ai->FuncTable[cntr].name != NULL) && (func == NO_FUNCTION);
- cntr++)
- {
- if ((strcmpi (arg1, ai->FuncTable[cntr].name)) == 0)
- func = ai->FuncTable[cntr].func;
- }
-
-
- /* preset the error return to zero */
- ai->pri_ret = 0L;
-
- if (func != NO_FUNCTION)
- {
- /* valid internal function, let's execute it */
-
- /* execute the function */
- (*(func)) (ai, (struct Message *) msg, args);
-
- /* successful command completion */
- retval = TRUE;
- }
- else
- {
- /* see if we are using ARexx */
- if (mh = HandlerData (ai, "AREXX"))
- {
- /* wasn't an internal function, so let's pass it to ARexx */
- if (!send_rexx_command (anchor, ai, mh))
- {
- /* ARexx failed (not present) */
- NotifyUser (NULL, "ARexx not present");
- }
- else
- /* successful command completion */
- retval = TRUE;
- }
- }
-
- return (retval);
- }
-
-
-
-
- /* mod_arexx.c
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- *
- * AREXX message handling routines
- */
- #include "mod.h"
-
- /* variables required for ARexx */
- struct data_arexx
- {
- struct MsgPort *rxport; /* ARexx message port */
- UBYTE *portname; /* ARexx message port name */
- UBYTE *extens; /* ARexx macro name extension */
- BOOL astatus; /* ARexx status */
- };
-
- /* ARexx message handling routines */
- BOOL send_rexx_command (UBYTE *, struct AppInfo *, struct MsgHandler *);
- VOID execute_command (struct RexxMsg *,struct AppInfo *,struct MsgHandler *);
- VOID reply_rexx_command (struct RexxMsg *,struct AppInfo *,struct MsgHandler *);
-
- /* ARexx Functions Prototypes */
- struct RexxMsg *CreateRexxMsg (struct MsgPort *, UBYTE *, UBYTE *);
- STRPTR CreateArgstring (UBYTE *, int);
- VOID DeleteRexxMsg (struct RexxMsg *);
- VOID DeleteArgstring (UBYTE *);
- BOOL IsRexxMsg (struct Message *);
-
- /* Required for ARexx processing */
- struct RxsLib *RexxSysBase = NULL;
-
- struct MsgHandler *setup_arexx (struct AppInfo * ai, UBYTE * pname,
- UBYTE * extens, BOOL immed)
- {
- UBYTE *portname = " ";
- register WORD cntr = 1;
- BOOL exist = TRUE, retval = FALSE;
- struct MsgHandler *mh = NULL;
- struct data_arexx *md = NULL;
-
- if (md = (struct data_arexx *)
- AllocMem (sizeof (struct data_arexx), MEMF_CLEAR))
- {
- md->portname = pname;
- md->extens = extens;
- if (RexxSysBase =
- (struct RsxLib *) OpenLibrary ("rexxsyslib.library", 0L))
- {
- Forbid (); /* forbid multi-tasking while we try to get a port */
-
- /* get an unique port name */
- while (exist)
- {
- /* create a name with our base name and a number */
- sprintf (portname, "%s_%d", md->portname, cntr);
-
- /* see if someone has already taken this name */
- if (!FindPort (portname)) exist = FALSE;
- cntr++;
- }
- /* allocate the port */
- if (md->rxport = CreatePort (portname, 0L))
- retval = TRUE;
- Permit (); /* permit multi-tasking again */
-
- if (mh = (struct MsgHandler *)
- AllocMem (sizeof (struct MsgHandler), MEMF_CLEAR))
- {
- mh->mh_Node.ln_Name = "AREXX";
- mh->mh_SigBits = (1L << md->rxport->mp_SigBit);
- mh->mh_Func[MH_OPEN] = NULL;
- mh->mh_Func[MH_HANDLE] = handle_arexx;
- mh->mh_Func[MH_CLOSE] = NULL;
- mh->mh_Func[MH_SHUTDOWN] = shutdown_arexx;
- mh->mh_Data = md;
-
- /* open immediately? */
- if (immed)
- {
- if (open_arexx (ai, mh))
- return (mh);
- }
- else
- return (mh);
-
- FreeMem (mh, sizeof (struct MsgHandler));
- }
- else
- NotifyUser (NULL, "Not enough memory");
-
- /* make a nice clean failure path */
- DeletePort (md->rxport);
- CloseLibrary ((struct Library *) RexxSysBase);
- md->rxport = NULL;
- RexxSysBase = NULL;
- }
- else
- NotifyUser (NULL, "Could not open rexxsyslib.library");
-
- FreeMem (md, sizeof (struct data_arexx));
- }
- return (mh);
- }
-
- BOOL open_arexx (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_arexx * md = mh->mh_Data;
-
- md->astatus = AR_EXECUTE;
- return (TRUE);
- }
-
- /* ARexx message processing */
- BOOL handle_arexx (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct RexxMsg *rmsg; /* incoming ARexx messages */
- struct data_arexx * md = mh->mh_Data;
-
- while (rmsg = (struct RexxMsg *) GetMsg (md->rxport))
- {
- if (rmsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
- {
- /* This is a reply to a previous message */
- if (rmsg->rm_Result1)
- {
- /* returned an error message */
- printf ("ARexx macro error\n");
- }
- /* Free up the resources used for an ARexx message */
-
- /* delete the argument that we originally sent */
- DeleteArgstring (rmsg->rm_Args[0]);
-
- /* delete the extended message */
- DeleteRexxMsg (rmsg);
-
- /* decrement the count of outstanding messages */
- ai->numcmds--;
- }
- else
- {
- /* We have received a command/function message */
- execute_command (rmsg, ai, mh);
- }
- }
- return (TRUE);
- }
-
- BOOL close_arexx (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_arexx * md = mh->mh_Data;
- md->astatus = AR_SUSPEND;
- return (TRUE);
- }
-
- BOOL shutdown_arexx (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_arexx * md = mh->mh_Data;
-
- if (mh)
- {
- if (md->rxport)
- DeletePort (md->rxport);
-
- Remove ((struct Node *) mh);
- FreeMem (mh, sizeof (struct MsgHandler));
- }
-
- if (RexxSysBase)
- CloseLibrary ((struct Library *) RexxSysBase);
-
- return (TRUE);
- }
-
- BOOL send_rexx_command (UBYTE * buff, struct AppInfo * ai,
- struct MsgHandler * mh)
- {
- struct MsgPort *rexxport; /* this will be rexx's port */
- struct RexxMsg *rexx_command_message; /* this is the message */
- struct data_arexx * md = mh->mh_Data;
-
- /* lock things temporarily */
- Forbid ();
-
- /* if ARexx is not active, just return FALSE */
- if (!(rexxport = FindPort (RXSDIR)))
- {
- Permit ();
- return (FALSE);
- }
-
- /* allocate a message packet for our command */
- /* note that this is a very important call. Much flexibility is */
- /* available to you here by using multiple host port names, etc. */
- if (!(rexx_command_message = CreateRexxMsg (md->rxport,
- md->extens,
- md->rxport->mp_Node.ln_Name)))
- {
- Permit ();
- return (FALSE);
- }
-
- /* create an argument string and install it in the message */
- if (!(rexx_command_message->rm_Args[0] =
- CreateArgstring (buff, strlen (buff))))
- {
- DeleteRexxMsg (rexx_command_message);
- Permit ();
- return (FALSE);
- }
-
- /* indicate that message is a command */
- rexx_command_message->rm_Action = RXCOMM;
-
- /* send the message */
- PutMsg (rexxport, (struct Message *) rexx_command_message);
-
- /* increment the number of outstanding messages */
- ai->numcmds++;
-
- Permit ();
-
- return (TRUE);
- }
-
- VOID execute_command (struct RexxMsg * rmsg, struct AppInfo * ai,
- struct MsgHandler * mh)
- {
- struct data_arexx * md = mh->mh_Data;
- UBYTE *cmd = ARG0 (rmsg);
-
- /* preset the ARexx error return values */
- ai->pri_ret = 5L;
- ai->sec_ret = 0L;
- ai->textrtn = NULL;
-
- /* Don't perform function if we are suspended */
- if (md->astatus == AR_EXECUTE)
- PerfFunc (ai, (struct Message *) rmsg, cmd);
- else
- ai->pri_ret = 100L;
-
- /* reply to the message */
- reply_rexx_command (rmsg, ai, mh);
- }
-
- /* Replys to a ARexx message */
- VOID reply_rexx_command (struct RexxMsg * rmsg, struct AppInfo * ai,
- struct MsgHandler * mh)
- {
- /* set an error code */
- if (ai->pri_ret == 0 && (rmsg->rm_Action & 1L << RXFB_RESULT))
- {
- ai->sec_ret = ai->textrtn ?
- (LONG) CreateArgstring (ai->textrtn, strlen (ai->textrtn))
- : (LONG) NULL;
- }
- rmsg->rm_Result1 = ai->pri_ret;
- rmsg->rm_Result2 = ai->sec_ret;
- ReplyMsg ((struct Message *) rmsg);
- }
-
-
-
- /* mod_dos.c
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- *
- * DOS command shell message handling routines
- */
- #include "mod.h"
-
- /* variables required for a DOS shell */
- struct data_dos
- {
- struct MsgPort *drport; /* DOS reply port */
- UBYTE *winspec; /* Shell window spec */
- UBYTE *closing_msg; /* Closing message */
- BPTR acons; /* Console file handle */
- struct StandardPacket *dmsg;/* DOS packet */
- UBYTE aprompt[25]; /* prompt */
- BOOL packet_out; /* is a READ outstanding? */
- UBYTE buff[BUFFLEN + 1]; /* used for reading user input */
- struct Process *atask; /* Our own process structure */
- BPTR old_CIS; /* Orig. console input stream */
- BPTR old_COS; /* Orig. console output stream */
- APTR old_ConsoleTask; /* Orig. console task */
- SHORT dstatus; /* The current status of the shell */
- };
-
- /* DOS message handling routines */
- VOID DisplayPrompt ( struct MsgHandler *mh );
- struct StandardPacket *setup_dos_message ( void );
- VOID send_read_packet (struct StandardPacket *,BPTR,struct MsgPort *, UBYTE *);
-
- struct MsgHandler *setup_dos (struct AppInfo * ai, UBYTE * winspec,
- UBYTE * prompt, UBYTE * close, BOOL immed)
- {
- struct MsgHandler *mh = NULL;
- struct data_dos *md = NULL;
-
- if (md = (struct data_dos *)
- AllocMem (sizeof (struct data_dos), MEMF_CLEAR))
- {
- /* initialize data */
- md->closing_msg = close;
- md->winspec = winspec;
- strcpy (md->aprompt, prompt);
-
- /* get the current process information */
- md->atask = (struct Process *) FindTask (0);
-
- /* make backups of the default task information */
- md->old_CIS = md->atask->pr_CIS;
- md->old_COS = md->atask->pr_COS;
- md->old_ConsoleTask = md->atask->pr_ConsoleTask;
- md->packet_out = FALSE;
-
- /* Mark shell window as being closed */
- md->dstatus = AS_CLOSED;
-
- /* set up a port for DOS replys */
- if (md->drport = CreatePort (NULL, 0L))
- {
- /* set up a DOS packet for the asynchronous read from the window */
- if (md->dmsg = setup_dos_message ())
- {
- mh = (struct MsgHandler *) AllocMem (sizeof (struct MsgHandler), MEMF_CLEAR);
-
- if (mh)
- {
- mh->mh_Node.ln_Name = "DOS";
- mh->mh_SigBits = (1L << md->drport->mp_SigBit);
- mh->mh_Func[MH_OPEN] = open_dos;
- mh->mh_Func[MH_HANDLE] = handle_dos;
- mh->mh_Func[MH_CLOSE] = close_dos;
- mh->mh_Func[MH_SHUTDOWN] = shutdown_dos;
- mh->mh_Data = md;
-
- /* open immediately? */
- if (immed)
- {
- if (open_dos (ai, mh))
- return (mh);
- }
- else
- return (mh);
-
- FreeMem (mh, sizeof (struct MsgHandler));
- }
- else
- NotifyUser (NULL, "Not enough memory");
-
- FreeMem (md->dmsg, sizeof (struct StandardPacket));
- md->dmsg = NULL;
- }
- DeletePort (md->drport);
- md->drport = NULL;
- }
- FreeMem (md, sizeof (struct data_dos));
- }
- return (mh);
- }
-
- BOOL open_dos (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_dos *md = mh->mh_Data;
- struct FileHandle *handle;
- if (!md->acons)
- {
- if (md->acons = Open (md->winspec, MODE_NEWFILE))
- {
- /* Set the standard input/output to this console window */
- md->atask->pr_CIS = md->acons;
- md->atask->pr_COS = md->acons;
-
- /* Convert the BPTR to a C pointer */
- handle = (struct FileHandle *) (md->acons << 2);
-
- /* Set the console task in case they open a window off ours */
- md->atask->pr_ConsoleTask = (APTR) handle->fh_Type;
-
- /* Display the prompt */
- DisplayPrompt (mh);
- md->dstatus = AS_OPEN;
-
- /* send a packet out for user input */
- if (!md->packet_out)
- {
- /* send a packet to DOS asking for user keyboard input */
- send_read_packet (md->dmsg, md->acons, md->drport, md->buff);
- md->packet_out = TRUE;
- }
-
- }
- }
- return ((BOOL) ((md->acons) ? TRUE : FALSE));
- }
- /* handle DOS messages */
- BOOL handle_dos (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_dos *md = mh->mh_Data;
- if (GetMsg (md->drport))
- {
- /* not out any more */
- md->packet_out = FALSE;
-
- /* If the shell CLOSE gadget was hit, or ^\ */
- if (md->dmsg->sp_Pkt.dp_Res1 == 0)
- {
- md->dstatus = AS_GOING;
- }
- else
- {
- md->buff[md->dmsg->sp_Pkt.dp_Res1 - 1] = 0;
-
- if (strlen (md->buff) > 0)
- {
- PerfFunc (ai, NULL, md->buff); /* perform the function */
-
- DisplayPrompt (mh); /* display the prompt */
- }
- else
- /* they entered a blank line, let's end the shell */
- md->dstatus = AS_GOING;
- }
- /* send out a packet for user input */
- if (!md->packet_out && md->dstatus >= AS_OPEN)
- {
- /* send a packet to DOS asking for user keyboard input */
- send_read_packet (md->dmsg, md->acons, md->drport, md->buff);
- md->packet_out = TRUE;
- }
- close_dos (ai, mh);
- }
- return (TRUE);
- }
-
- BOOL close_dos (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_dos *md = mh->mh_Data;
-
- if (md->dstatus == AS_GOING)
- {
- /* User has indicated that he wants to close the command shell. */
- md->dstatus = AS_CLOSING;
- Write (md->acons, md->closing_msg, (LONG) strlen (md->closing_msg));
- }
-
- if (md->dstatus == AS_CLOSING && !ai->numcmds)
- {
- if (md->acons)
- {
- /* safely restore the default information */
- md->atask->pr_CIS = md->old_CIS;
- md->atask->pr_COS = md->old_COS;
- md->atask->pr_ConsoleTask = md->old_ConsoleTask;
-
- /* close the console window */
- Close (md->acons);
- }
-
- md->dstatus = AS_CLOSED;
- md->acons = NULL;
- }
- return ((BOOL) ((md->acons) ? TRUE : FALSE));
- }
-
- BOOL shutdown_dos (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_dos *md = mh->mh_Data;
- if (mh)
- {
- if (md)
- {
- if (md->acons)
- md->dstatus = AS_GOING;
- close_dos (ai, mh);
-
- if (md->drport)
- DeletePort (md->drport);
-
- if (md->dmsg)
- FreeMem (md->dmsg, sizeof (struct StandardPacket));
- }
-
- Remove ((struct Node *) mh);
- FreeMem (mh, sizeof (struct MsgHandler));
- }
-
- return (TRUE);
- }
-
- VOID DisplayPrompt (struct MsgHandler * mh)
- {
- struct data_dos *md = mh->mh_Data;
-
- Write (md->acons, md->aprompt, (LONG) strlen (md->aprompt));
- }
-
- struct StandardPacket *setup_dos_message ()
- {
- struct StandardPacket *new_packet;
-
- /* get a packet */
- if (new_packet = (struct StandardPacket *)
- AllocMem (sizeof (struct StandardPacket), MEMF_CLEAR))
- {
- new_packet->sp_Msg.mn_Node.ln_Name =
- (UBYTE *) & (new_packet->sp_Pkt);
- new_packet->sp_Pkt.dp_Link = &(new_packet->sp_Msg);
- }
- return (new_packet);
- }
-
- VOID send_read_packet (struct StandardPacket * dos_message,
- BPTR console_fh,
- struct MsgPort * dos_reply_port,
- UBYTE * buff)
- {
- struct FileHandle *file_handle;
-
- /* change a BPTR to a REAL pointer */
- file_handle = (struct FileHandle *) (console_fh << 2);
- /* setup the packet for reading */
- dos_message->sp_Pkt.dp_Arg1 = file_handle->fh_Arg1;
- dos_message->sp_Pkt.dp_Arg2 = (LONG) buff;
- dos_message->sp_Pkt.dp_Arg3 = BUFFLEN;
- dos_message->sp_Pkt.dp_Type = ACTION_READ;
- dos_message->sp_Pkt.dp_Port = dos_reply_port;
- dos_message->sp_Msg.mn_ReplyPort = dos_reply_port;
-
- /* now send it */
- PutMsg (file_handle->fh_Type, (struct Message *) dos_message);
- }
-
-
- /* mod_idcmp.c
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- *
- * IDCMP gadget/menu/keyboard message handling routines
- */
-
- #include "mod.h"
-
- #define idcmp_flags (CLOSEWINDOW | RAWKEY | MOUSEMOVE | MOUSEBUTTONS \
- | INTUITICKS | GADGETDOWN | GADGETUP | MENUPICK)
-
- #define SHIFTED (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
- #define ALTED (IEQUALIFIER_LALT | IEQUALIFIER_RALT)
-
- /* variables required for IDCMP message handling */
- struct data_idcmp
- {
- struct MsgPort *msgport; /* Message port */
- struct NewWindow *nw; /* NewWindow pointer */
- struct Menu *menu; /* Menu strip pointer */
- WORD *KeyFunctions; /* Keyboard function map */
- struct Window *win; /* Window */
- struct EGadget *ActiveGad; /* Currrently active gadget */
- struct IOStdReq ioreq; /* Rawkey conversion IO request */
- };
-
- BOOL setup_key_array (struct data_idcmp * mh, struct KeyboardCMD * KeyArray);
- VOID shutdown_key_array (struct data_idcmp *);
- LONG DeadKeyConvert(struct IntuiMessage * msg, UBYTE * kbuffer, LONG kbsize, struct KeyMap * kmap);
- VOID CloseWindowSafely (struct Window * win);
- VOID HandleKeyEvent(struct AppInfo *,struct MsgHandler *,struct IntuiMessage * msg);
- VOID HandleGadgEvent(struct AppInfo *,struct MsgHandler *,struct IntuiMessage * msg);
- VOID HandleMenuEvent(struct AppInfo *,struct MsgHandler *,struct IntuiMessage * msg);
-
- /* Required for DeadKeyConvert processing */
- struct ConsoleDevice *ConsoleDevice = NULL;
-
- /* setup the resources required for IDCMP processing */
- struct MsgHandler *setup_idcmp (struct AppInfo * ai,
- struct NewWindow * nw,
- struct KeyboardCMD * kba,
- struct Menu * menu, BOOL immed)
- {
- struct MsgHandler *mh = NULL;
- struct data_idcmp *md = NULL;
-
- if (md = (struct data_idcmp *)
- AllocMem (sizeof (struct data_idcmp), MEMF_CLEAR))
- {
- md->nw = nw;
- md->menu = menu;
- if (setup_key_array (md, kba))
- {
- if (md->msgport = CreatePort (NULL, 0))
- {
- if (mh = (struct MsgHandler *)
- AllocMem (sizeof (struct MsgHandler), MEMF_CLEAR))
- {
- mh->mh_SigBits = (1L << md->msgport->mp_SigBit);
- mh->mh_Func[MH_OPEN] = open_idcmp;
- mh->mh_Func[MH_HANDLE] = handle_idcmp;
- mh->mh_Func[MH_CLOSE] = close_idcmp;
- mh->mh_Func[MH_SHUTDOWN] = shutdown_idcmp;
- mh->mh_Data = md;
-
- if (immed)
- {
- if (open_idcmp (ai, mh))
- return (mh);
- }
- else
- return (mh);
-
- FreeMem (mh, sizeof (struct MsgHandler));
- }
- else
- NotifyUser (NULL, "Not enough memory");
- }
- else
- NotifyUser (NULL, "Could not create IDCMP port");
- }
- FreeMem (md, sizeof (struct data_idcmp));
- }
- return (mh);
- }
-
- /* activate IDCMP handler */
- BOOL open_idcmp (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_idcmp *md = mh->mh_Data;
-
- if (!(md->win))
- {
- /* Open an Intuition window */
- md->nw->IDCMPFlags = NULL;
- if (md->win = OpenWindow (md->nw))
- {
- /* Attach the menu strip. You should pass it thru the AdjustMenu
- * function that is shown in the 1.3 RKM Libraries & Devices menu
- * example. */
- SetMenuStrip (md->win, md->menu);
-
- /* set up the message port information */
- md->win->UserPort = md->msgport;
- ModifyIDCMP (md->win, idcmp_flags);
-
- return (TRUE);
- }
- else
- NotifyUser (NULL, "Could not open window");
- }
- return (FALSE);
- }
-
- /* Intuition message processing */
- BOOL handle_idcmp (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_idcmp *md = mh->mh_Data;
- struct IntuiMessage *imsg; /* incoming Intuition messages */
- struct IntuiMessage *fmsg, *tmsg; /* for filtering messages */
- struct Window * win; /* only used for filtering messages */
- struct IntuiMessage nmsg; /* copy of the message */
-
- while (imsg = (struct IntuiMessage *) GetMsg (md->msgport))
- {
- /* Filter out excessive mouse-moves (oldest first) */
- if (imsg->Class == MOUSEMOVE)
- {
- win = imsg->IDCMPWindow;
- Forbid ();
- fmsg = (struct IntuiMessage *)
- (md->msgport->mp_MsgList.lh_Head);
- while (tmsg = (struct IntuiMessage *)
- (fmsg->ExecMessage.mn_Node.ln_Succ))
- {
- if (fmsg->IDCMPWindow == win &&
- fmsg->Class == MOUSEMOVE)
- {
- Remove ((struct Node *) fmsg);
- ReplyMsg ((struct Message *) imsg);
- imsg = fmsg;
- }
- fmsg = tmsg;
- }
- Permit ();
- }
- /* Filter out excessive key repeats here. Amiga Mail article by
- * Michael Sinz IV-37 Paced Repeat Key */
-
- /* copy the message so that we can reply to it */
- CopyMem ( (APTR)imsg, (APTR)&nmsg, sizeof (struct IntuiMessage) );
-
- /* Reply to the message now that we're done with it */
- ReplyMsg ((struct Message *) imsg);
-
- /* Process Intuition events */
- switch (nmsg.Class)
- {
- /* Handle the close window gadget */
- case CLOSEWINDOW:
- QuitFunc (ai, (struct Message *) &nmsg, NULL);
- break;
-
- /* Handle keyboard events */
- case RAWKEY:
- HandleKeyEvent (ai, mh, &nmsg);
- break;
-
- /* Handle events that pertain to gadgets */
- case INTUITICKS:
- case MOUSEMOVE:
- case MOUSEBUTTONS:
- case GADGETDOWN:
- case GADGETUP:
- HandleGadgEvent (ai, mh, &nmsg);
- break;
-
- /* Handle menu events */
- case MENUPICK:
- HandleMenuEvent (ai, mh, &nmsg);
- break;
- }
- }
- return (TRUE);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /* hide IDCMP message handler */
- BOOL close_idcmp (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_idcmp *md = mh->mh_Data;
-
- if (mh)
- {
- if (md->win)
- {
- /* save current settings */
- md->nw->Width = md->win->Width;
- md->nw->Height = md->win->Height;
- md->nw->LeftEdge = md->win->LeftEdge;
- md->nw->TopEdge = md->win->TopEdge;
-
- /* clear the menu strip if there is one */
- if (md->win->MenuStrip)
- ClearMenuStrip (md->win);
-
- /* close the window */
- CloseWindowSafely (md->win);
- md->win = NULL;
- }
- }
- return (TRUE);
- }
-
- /* free resources for IDCMP message handler */
- BOOL shutdown_idcmp (struct AppInfo * ai, struct MsgHandler * mh)
- {
- struct data_idcmp *md = mh->mh_Data;
-
- if (mh)
- {
- close_idcmp (ai, mh); /* close window */
- shutdown_key_array (md); /* free keyboard array */
-
- DeletePort (md->msgport); /* delete IDCMP port */
- md->msgport = NULL;
- }
- return (TRUE);
- }
-
- /* safely close a window that shares a message port with another window */
- VOID CloseWindowSafely (struct Window * win)
- {
- struct IntuiMessage * msg, * succ;
-
- Forbid ();
-
- msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
- while (succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ)
- {
- if (msg->IDCMPWindow == win)
- {
- Remove ((struct Node *)msg);
- ReplyMsg ((struct Message *)msg);
- }
- msg = succ;
- }
- win->UserPort = NULL;
- ModifyIDCMP (win, NULL);
-
- Permit ();
- CloseWindow (win);
- }
-
- /* Allocate resources for handling keyboard input */
- BOOL setup_key_array (struct data_idcmp * md, struct KeyboardCMD * KeyArray)
- {
- register WORD cntr;
-
- /* Allow for NULL specification of a keyboard command array */
- if (!KeyArray)
- return (TRUE);
-
- /* Prepare for DeadKeyConvert */
- if (!(OpenDevice ("console.device", -1L,
- (struct IORequest *) & (md->ioreq), 0L)))
- {
- ConsoleDevice = (struct ConsoleDevice *) md->ioreq.io_Device;
-
- /* Allocate memory for the keyboard function map */
- if (md->KeyFunctions = AllocMem ((sizeof (WORD) * MAXKEYS), MEMF_CLEAR))
- {
- /* read in the key assignments */
- for (cntr = 0; KeyArray[cntr].key != NULL; cntr++)
- md->KeyFunctions[KeyArray[cntr].key] = KeyArray[cntr].funcID;
- return (TRUE);
- }
- else
- NotifyUser (NULL, "Not enough memory");
-
- CloseDevice ((struct IORequest *) & (md->ioreq));
- }
- else
- NotifyUser (NULL, "Could not open console.device");
-
- return (FALSE);
- }
-
- /* Release resources for handling keyboard input */
- VOID shutdown_key_array (struct data_idcmp * md)
- {
- if (md)
- {
- if (md->KeyFunctions)
- FreeMem (md->KeyFunctions, (sizeof (WORD) * MAXKEYS));
- md->KeyFunctions = NULL;
-
- if (ConsoleDevice)
- CloseDevice ((struct IORequest *) & (md->ioreq));
- }
- }
-
- /* Keyboard handling routines */
- VOID HandleKeyEvent (struct AppInfo * ai, struct MsgHandler * mh,
- struct IntuiMessage * msg)
- {
- struct data_idcmp *md = mh->mh_Data;
- WORD FuncID = NO_FUNCTION;
- WORD key, cur;
- UBYTE buffer[17];
-
- strcpy (buffer, " ");
- key = (WORD) DeadKeyConvert (msg, buffer, 15L, 0L);
- if (key > 0)
- {
- /* Get the ASCII value of the key that was pressed */
- cur = buffer[0];
-
- /* Check to see if it was a special key; like a Function key, Help, or
- * the Arrow keys. Could also do additional checking for ALT, AMIGA
- * and CTRL qualifiers by adding in a weight for each one. */
- if (key > 1 && cur == 155)
- cur = SPECIAL + buffer[1];
-
- /* Get the function number assigned to this key */
- FuncID = md->KeyFunctions[cur];
-
- if (FuncID != NO_FUNCTION)
- /* Perform the function assigned to this key. */
- PerfFunc (ai, NULL, ai->FuncTable[FuncID].name);
- else
- {
- /* No function has been defined for this key, so you could
- * do other processing to it. */
- }
- }
- }
-
- /* Convert Raw keys to Vanilla keys */
- LONG DeadKeyConvert (msg, kbuffer, kbsize, kmap)
- struct IntuiMessage *msg;
- UBYTE *kbuffer;
- LONG kbsize;
- struct KeyMap *kmap;
- {
- static struct InputEvent ievent =
- {NULL, IECLASS_RAWKEY, 0, 0, 0};
-
- if (msg->Class != RAWKEY)
- return (-2);
- ievent.ie_Code = msg->Code;
- ievent.ie_Qualifier = msg->Qualifier;
- ievent.ie_position.ie_addr = *((APTR *) msg->IAddress);
-
- return (RawKeyConvert (&ievent, kbuffer, kbsize, kmap));
- }
-
- /* Gadget handling routine */
- VOID HandleGadgEvent (struct AppInfo * ai, struct MsgHandler * mh,
- struct IntuiMessage * msg)
- {
- struct data_idcmp *md = mh->mh_Data;
- struct EGadget *egad = (struct EGadget *) msg->IAddress;
- WORD FuncID = NO_FUNCTION;
- static ULONG glsecs = 0L, glmics = 0L; /* For Gadget DoubleClick */
-
- switch (msg->Class)
- {
- /* Check to see if gadget is being held down and if there is a
- * function to perform while it is being held. */
- case MOUSEMOVE:
- case INTUITICKS:
- if (md->ActiveGad &&
- md->ActiveGad->eg_Gadget.Flags & SELECTED)
- {
- FuncID = md->ActiveGad->eg_Funcs[EG_HOLD];
- }
- break;
-
- /* Indicate that there is no active gadget now. */
- case MOUSEBUTTONS:
- if (msg->Code == SELECTUP)
- md->ActiveGad = NULL;
- break;
-
- /* Check to see if there is a function to perform on downpress or
- * double-click of the gadget. */
- case GADGETDOWN:
-
- /* Set the active gadget. Only one gadget can EVER be active
- * at a time (Intuition rule). */
- md->ActiveGad = egad;
-
- FuncID = egad->eg_Funcs[EG_DOWNPRESS];
- if (egad->eg_Funcs[EG_DBLCLICK] != NO_FUNCTION)
- {
-
- /* If the gadget has a double-click function, then check to
- * see if it has been double-clicked. Notice that if there
- * is a double-click function, then it over-rules the
- *downpress function. */
- if (DoubleClick (glsecs, glmics, msg->Seconds, msg->Micros))
- FuncID = egad->eg_Funcs[EG_DBLCLICK];
- else
- {
- glsecs = msg->Seconds;
- glmics = msg->Micros;
- }
- }
- break;
-
- /* Check to see if there is a function to perform on release of the
- * gadget. */
- case GADGETUP:
- /* Clear the active gadget variable */
- md->ActiveGad = NULL;
-
- FuncID = egad->eg_Funcs[EG_RELEASE];
- break;
- }
-
- /* Perform the function if there is one. */
- if (FuncID != NO_FUNCTION)
- PerfFunc (ai, NULL, ai->FuncTable[FuncID].name);
- }
-
- /* Menu handling routine */
- VOID HandleMenuEvent (struct AppInfo * ai, struct MsgHandler * mh,
- struct IntuiMessage * msg)
- {
- struct EMenuItem *item;
- UWORD selection = msg->Code;
-
- /* Shut down menu events while we're processing these. Any function that
- * opens its own window and ignores events from the main window, should
- * also set a busy pointer in the main window. */
- msg->IDCMPWindow->Flags |= RMBTRAP;
-
- /* Process all menu events */
- while ((selection != MENUNULL) && (!ai->Done))
- {
- /* Get the Extended MenuItem structure address */
- item = (struct EMenuItem *)
- ItemAddress (msg->IDCMPWindow->MenuStrip, (LONG) selection);
-
- /* Mutual Excluded items should all call the same function. And that
- * function should do any processing based on the currently selected
- * item. */
- PerfFunc (ai, NULL, ai->FuncTable[item->emi_MenuID].name);
-
- /* Get the next selection */
- selection = item->emi_Item.NextSelect;
- }
-
- /* Turn menu events back on. */
- msg->IDCMPWindow->Flags &= ~RMBTRAP;
- }
-
-
-
-
-
- /* mod_funcs.c
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- *
- * application specific functions
- *
- */
-
- #include "mod.h"
-
- /*--- check to see if the project has been changed ---*/
- BOOL CheckForChanges (struct AppInfo * ai)
- {
- BOOL cancel = FALSE;
- UBYTE pname[255];
-
- /* See if there is a name for our project */
- strcpy (pname, ai->ProjName);
- if (strlen (pname) < 1)
- strcpy (pname, "<untitled>");
-
- /* Check to see if any changes have been made to our project */
- if (ai->Changed)
- {
-
- /* Bring up a requester stating:
- * project (pname) has been changed, do you want to save first?
- * prompt for Yes | No | Cancel
- *
- * Yes: call the SaveFunc(NULL, win, NULL) function.
- * No: fall through.
- * Cancel: set cancel=TRUE.
- */
-
- /*
- * also set ai->pri_ret so that scripts can act accordingly
- *
- * Yes: 0
- * No: 0
- * Cancel: 5
- */
- }
- return (cancel);
- }
-
- VOID NewFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- BOOL cancel;
-
- printf ("`New' function\n");
-
- cancel = CheckForChanges (ai);
- if (!cancel)
- {
- /* Free up the previous project here... */
-
- /* Prepare for a New project here... */
- strcpy (ai->ProjName, "");
- ai->Changed = FALSE;
- }
- }
-
-
-
-
-
-
-
- VOID OpenFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- BOOL cancel;
-
- printf ("`Open' function\n");
-
- cancel = CheckForChanges (ai);
- if (!cancel)
- {
- /* see if an argument was passed */
- if (strlen (args) > 0)
- {
- printf ("%s was passed\n", args);
- strcpy (ai->ProjName, args);
- }
- else
- {
- /*
- * Bring up your file requester here. Remember to check for cancel
- * being pressed...
- */
- strcpy (ai->ProjName, "Named");
- }
-
- /* Open a new project here... */
- ai->Changed = FALSE;
- }
- }
-
- VOID SaveFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Save' function\n");
-
- if (strlen (ai->ProjName) == 0)
- {
- /* Not named yet, so let's get a name */
- SaveAsFunc (ai, msg, args);
- }
- else if (ai->Changed)
- {
- /* Save your project here ... */
- ai->Changed = FALSE;
- }
- }
-
- VOID SaveAsFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Save As' function\n");
-
- /* see if an argument was passed */
- if (strlen (args) > 0)
- {
- /* they passed a file name to save as */
- printf ("%s was passed\n", args);
- strcpy (ai->ProjName, args);
- }
- else
- {
- /*
- * Bring up your file requester here so that user can name the project.
- * Only set the Changed flag to FALSE if the user successfully returns
- * a file name (doesn't hit CANCEL).
- */
- strcpy (ai->ProjName, "Named");
- }
-
- /* Save your project here ... */
- ai->Changed = FALSE;
- }
-
-
- VOID AboutFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`About' function\n");
-
- /* return a text value */
- ai->textrtn = "ModEngine 1.00 23-Feb-90";
- }
-
-
- VOID QuitFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Quit' function\n");
-
- /* Inform the main loop that we are done */
- ai->Done = TRUE;
- }
-
-
- VOID ChooseFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Choose a Tool' function\n");
- }
-
-
- VOID DefineFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Change Tool Settings' function\n");
- }
-
- VOID UndoFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Undo' function\n");
- }
-
-
- VOID HelpFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Help' function\n");
- }
-
-
- VOID ArrowFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Arrow' function\n");
- }
-
-
- VOID ShellFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Shell' function\n");
- HandlerFunc (ai, "DOS", MH_OPEN);
- }
-
-
- VOID WindowFunc (struct AppInfo *ai, struct Message *msg, UBYTE * args)
- {
- printf ("`Window' function\n");
- if (strcmpi (args, "CLOSE") == 0)
- HandlerFunc (ai, "IDCMP", MH_CLOSE);
- else
- HandlerFunc (ai, "IDCMP", MH_OPEN);
- }
-
-
-
- /* mod_misc.c
- * Copyright (C) 1990 Commodore-Amiga, Inc.
- * written by David N. Junod
- */
- #include "mod.h"
-
- /*--- AutoRequest support variables ---*/
- extern struct TextAttr Topaz80;
-
- UBYTE ErrorBuffer[255] = "\\000";
- struct IntuiText ErrorText =
- {2, 1, JAM1, 20, 15, &Topaz80, &ErrorBuffer[0], NULL};
-
- struct IntuiText ctext =
- {AUTOFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, AUTOLEFTEDGE,
- AUTOTOPEDGE, &Topaz80, " CONTINUE ", NULL
- };
-
- BOOL NotifyUser (struct Window * win, UBYTE * msg)
- {
- struct IntuiText *errortext;
- SHORT arwidth, arheight = 60, arwadj = 60;
-
- sprintf (ErrorBuffer, "%s\\000", msg);
- errortext = &ErrorText;
- arwidth = IntuiTextLength (errortext) + arwadj;
- return ((BOOL) AutoRequest (win, errortext, NULL, &ctext,
- 0, 0, arwidth, arheight));
- }
-
- /* macro1.mod */
- /* modengine1 test rexx script #1 */
- /* run from ModEngine shell: macro1 */
-
- options results /* request string to be returned */
- WINDOW CLOSE
- NEW
- say 'rc=' rc 'result=' result
- OPEN my titled
- say 'rc=' rc 'result=' result
- OPEN
- say 'rc=' rc 'result=' result
- ABOUT
- say 'rc=' rc 'result=' resul
- SAVEAS my titled
- say 'rc=' rc 'result=' result
- WINDOW OPEN
- say 'rc=' rc 'result=' result
-
- /* rxtest.rexx */
- /* modengine1 test rexx script #2 */
- /* run from CLI: rx rxtest */
-
- options results /* turn on string results */
- address 'OURAPP_1'
- NEW
- ABOUT
- say 'rc=' rc 'result=' result
- SAVEAS my titled
- OPEN my titled
- SAVE
- MACRO2
- address
-
-
-